package com.cg.service.impl;

import com.cg.constant.RedisConstant;
import com.cg.dto.ChatSessionDTO;
import com.cg.dto.ChatMessageDTO;
import com.cg.service.AiChatService;
import com.cg.service.ChatMemoryService;
import com.cg.service.InterviewSessionService;
import com.cg.service.AiCodeHelperService;
import com.cg.service.InterviewAiService;

import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.memory.ChatMemory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.ArrayList;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * AI聊天服务实现类
 */
@Service
@Slf4j
public class AiChatServiceImpl implements AiChatService {

    @Autowired
    private ChatModel myQwenChatModel;

    @Autowired
    private ChatModel interviewQwenChatModel;

    @Autowired
    private AiCodeHelperService aiCodeHelperService;

    @Autowired
    private InterviewAiService interviewAiService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;



    @Autowired
    private ChatMemoryService chatMemoryService;

    @Autowired
    private InterviewSessionService interviewSessionService;

    private static final String SYSTEM_MESSAGE = """
            你是一个专业的编程学习和求职面试助手，专门帮助用户提升编程技能和准备技术面试。

你的主要职责包括：
1. 解答编程技术问题，提供清晰的代码示例和解释
2. 协助用户准备技术面试，包括算法、数据结构、系统设计等
3. 提供编程学习建议和职业规划指导
4. 分析简历和项目，给出改进建议

请始终保持专业、友好的态度，提供准确、实用的建议。
            """;

    /**
     * 基础聊天方法（带记忆功能）
     * @param userId 用户ID
     * @param sessionId 会话ID
     * @param message 用户消息
     * @return AI回复
     */
    @Override
    public String chat(Long userId, Long sessionId, String message) {
        try {
            // 消息内容验证
            if (message == null || message.trim().isEmpty()) {
                log.warn("收到空消息，跳过处理: userId={}, sessionId={}", userId, sessionId);
                return "消息内容不能为空";
            }
            
            // 获取ChatMemory
            ChatMemory chatMemory = chatMemoryService.getChatMemory(sessionId);
            
            // 先添加用户消息到ChatMemory
            chatMemory.add(UserMessage.from(message));
            
            // 构建发送给AI模型的完整消息列表：系统消息 + ChatMemory中的历史消息
            List<ChatMessage> messagesToSend = new ArrayList<>();
            messagesToSend.add(SystemMessage.from(SYSTEM_MESSAGE)); // 始终添加系统消息
            messagesToSend.addAll(chatMemory.messages()); // 添加ChatMemory中的历史消息
            
            log.info("准备发送给AI的消息数量: {}, 包含系统消息: {}", 
                    messagesToSend.size(), 
                    messagesToSend.stream().anyMatch(msg -> msg instanceof SystemMessage));
            
            // 使用完整的消息列表生成AI回复
            ChatResponse chatResponse = myQwenChatModel.chat(messagesToSend);
            AiMessage aiMessage = chatResponse.aiMessage();
            
            // 添加AI回复到ChatMemory
            chatMemory.add(aiMessage);
            
            // 保存用户消息到数据库（包含去重逻辑）
            chatMemoryService.addUserMessage(sessionId, message);
            
            // 保存AI回复到数据库
            chatMemoryService.addAiMessage(sessionId, aiMessage.text());
            
            // 更新会话标题（如果是第一条消息）
            // 只有当会话中只有系统消息和当前用户消息时，才更新标题
            if (messagesToSend.size() == 2 && messagesToSend.get(0) instanceof SystemMessage && messagesToSend.get(1) instanceof UserMessage) {
                String title = message.length() > 50 ? message.substring(0, 50) + "..." : message;
                chatMemoryService.updateSessionTitle(sessionId, title);
            }
            
            log.info("AI对话完成，sessionId={}, userId={}, 消息数量={}", sessionId, userId, messagesToSend.size());
            return aiMessage.text();
            
        } catch (Exception e) {
            log.error("AI对话失败: userId={}, sessionId={}, error={}", userId, sessionId, e.getMessage(), e);
            throw new RuntimeException("AI对话失败", e);
        }
    }

    /**
     * 基础聊天方法（兼容旧接口）
     * @param message 用户消息
     * @return AI回复
     */
    @Override
    public String chat(String message) {
        // 如果没有userId，使用默认的系统消息
        SystemMessage systemMessage = SystemMessage.from(SYSTEM_MESSAGE);
        UserMessage userMessage = UserMessage.from(message);
        ChatResponse chatResponse = myQwenChatModel.chat(systemMessage, userMessage);
        AiMessage aiMessage = chatResponse.aiMessage();
        log.info("AI 输出：" + aiMessage.toString());
        return aiMessage.text();
    }

    /**
     * 使用用户消息对象进行聊天
     * @param userMessage 用户消息对象
     * @return AI回复
     */
    @Override
    public String chatWithMessage(UserMessage userMessage) {
        ChatResponse chatResponse = myQwenChatModel.chat(userMessage);
        AiMessage aiMessage = chatResponse.aiMessage();
        log.info("AI 输出：" + aiMessage.toString());
        return aiMessage.text();
    }

    /**
     * 流式对话功能（带记忆功能）
     * @param userId 用户ID
     * @param sessionId 会话ID
     * @param message 用户消息
     * @return 流式响应
     */
    @Override
    public Flux<String> chatStream(Long userId, Long sessionId, String message) {
        try {
            if (message == null || message.trim().isEmpty()) {
                log.warn("收到空消息（流式），跳过处理: userId={}, sessionId={}", userId, sessionId);
                return Flux.error(new IllegalArgumentException("消息内容不能为空"));
            }

            // 1) 将用户消息写入 ChatMemory 与 数据库
            ChatMemory chatMemory = chatMemoryService.getChatMemory(sessionId);
            chatMemory.add(UserMessage.from(message));
            chatMemoryService.addUserMessage(sessionId, message);

            // 若会话标题仍为默认占位（新会话/新对话），在用户首次发消息后立刻更新为前10字+"..."
            try {
                ChatSessionDTO currentSessionMeta = chatMemoryService.getUserSessions(userId)
                        .stream()
                        .filter(s -> s.getSessionId().equals(sessionId))
                        .findFirst()
                        .orElse(null);
                if (currentSessionMeta != null) {
                    String titleNow = currentSessionMeta.getSessionTitle();
                    if ("新会话".equals(titleNow) || "新对话".equals(titleNow)) {
                        String title = message.trim();
                        if (title.length() > 10) {
                            title = title.substring(0, 10) + "...";
                        }
                        chatMemoryService.updateSessionTitle(sessionId, title);
                    }
                }
            } catch (Exception e) {
                log.warn("会话标题即时更新失败（可忽略）: sessionId={}, error={}", sessionId, e.getMessage());
            }

            // 2) 通过已有的流式服务获取 token 流
            StringBuilder aiResponseBuilder = new StringBuilder();
            return aiCodeHelperService.chatStream(sessionId.intValue(), message)
                    .doOnNext(token -> {
                        if (token != null) {
                            aiResponseBuilder.append(token);
                        }
                    })
                    .doOnComplete(() -> {
                        try {
                            String fullAiText = aiResponseBuilder.toString();
                            // 写入 ChatMemory 与 数据库
                            chatMemory.add(AiMessage.from(fullAiText));
                            chatMemoryService.addAiMessage(sessionId, fullAiText);
                            log.info("AI流式对话完成，sessionId={}, userId={}, 长度={}", sessionId, userId, fullAiText.length());
                        } catch (Exception e) {
                            log.error("保存AI流式结果失败: userId={}, sessionId={}, error={}", userId, sessionId, e.getMessage(), e);
                        }
                    })
                    .doOnError(e -> log.error("AI流式对话失败: userId={}, sessionId={}, error={}", userId, sessionId, e.getMessage(), e));
        } catch (Exception e) {
            log.error("chatStream 异常: userId={}, sessionId={}, error={}", userId, sessionId, e.getMessage(), e);
            return Flux.error(new RuntimeException("流式对话失败", e));
        }
    }

    /**
     * 基于面试提示词/用户输入的流式对话（面试专用，会话ID为面试会话ID）
     * 仅使用面试会话表进行持久化，不再访问普通聊天会话，避免“会话不存在”。
     */
    @Override
    public Flux<String> interviewStream(Long userId, Long sessionId, String prompt) {
        try {
            if (prompt == null || prompt.trim().isEmpty()) {
                log.warn("收到空消息（面试流式），跳过处理: userId={}, sessionId={}", userId, sessionId);
                return Flux.error(new IllegalArgumentException("消息内容不能为空"));
            }

            StringBuilder aiResponseBuilder = new StringBuilder();
            // 面试场景：使用专门的面试AI服务，支持更长的输入内容
            return interviewAiService.chatStream(sessionId.intValue(), prompt)
                    .doOnNext(token -> {
                        if (token != null) {
                            aiResponseBuilder.append(token);
                        }
                    })
                    .doOnComplete(() -> {
                        try {
                            String fullAiText = aiResponseBuilder.toString();
                            interviewSessionService.addAssistantMessage(sessionId, fullAiText);
                            log.info("面试流式对话完成，sessionId={}, userId={}, 长度={}", sessionId, userId, fullAiText.length());
                        } catch (Exception e) {
                            log.error("保存面试AI流式结果失败: userId={}, sessionId={}, error={}", userId, sessionId, e.getMessage(), e);
                        }
                    })
                    .doOnError(e -> log.error("面试流式对话失败: userId={}, sessionId={}, error={}", userId, sessionId, e.getMessage(), e));
        } catch (Exception e) {
            log.error("interviewStream 异常: userId={}, sessionId={}, error={}", userId, sessionId, e.getMessage(), e);
            return Flux.error(new RuntimeException("流式对话失败", e));
        }
    }

    /**
     * 流式对话功能（兼容旧接口）
     * @param memoryId 会话记忆ID
     * @param message 用户消息
     * @return 流式响应
     */
    @Override
    public Flux<String> chatStream(int memoryId, String message) {
        return aiCodeHelperService.chatStream(memoryId, message);
    }

    /**
     * 保存AI对话历史（使用新的ChatMemory系统）
     * @param userId 用户ID
     * @param aiTalkList 对话列表
     */
    @Override
    public void saveAiTalks(Long userId, List<Object> aiTalkList) {
        try {
            // 获取或创建当前会话
            ChatSessionDTO currentSession = chatMemoryService.getOrCreateCurrentSession(userId);
            Long sessionId = currentSession.getSessionId();
            
            // 处理对话列表，保存到ChatMemory系统
            for (Object talk : aiTalkList) {
                try {
                    String role = null;
                    String content = null;
                    
                    // 处理Map对象（前端传递的JSON对象）
                    if (talk instanceof Map) {
                        Map<?, ?> talkMap = (Map<?, ?>) talk;
                        role = (String) talkMap.get("role");
                        content = (String) talkMap.get("content");
                    } else {
                        // 兼容旧系统，尝试获取role和content属性
                        try {
                            role = (String) talk.getClass().getMethod("getRole").invoke(talk);
                            content = (String) talk.getClass().getMethod("getContent").invoke(talk);
                        } catch (Exception e) {
                            log.warn("无法通过反射获取对话对象属性: {}", talk, e);
                            continue;
                        }
                    }
                    
                    // 验证role和content
                    if (role != null && content != null && !content.trim().isEmpty()) {
                        if ("user".equalsIgnoreCase(role)) {
                            chatMemoryService.addUserMessage(sessionId, content.trim());
                        } else if ("assistant".equalsIgnoreCase(role)) {
                            chatMemoryService.addAiMessage(sessionId, content.trim());
                        }
                    } else {
                        log.warn("跳过无效的对话对象: role={}, content={}", role, content);
                    }
                } catch (Exception e) {
                    log.warn("处理对话对象失败: {}", talk, e);
                }
            }
            
            // 保存到Redis（兼容旧系统）
            String redisKey = RedisConstant.AI_CONTENT + userId;
            List<Map<String, String>> conversations = aiTalkList.stream()
                    .map(talk -> {
                        Map<String, String> map = new HashMap<>();
                        try {
                            String role = null;
                            String content = null;
                            
                            // 处理Map对象
                            if (talk instanceof Map) {
                                Map<?, ?> talkMap = (Map<?, ?>) talk;
                                role = (String) talkMap.get("role");
                                content = (String) talkMap.get("content");
                            } else {
                                // 兼容旧系统
                                role = (String) talk.getClass().getMethod("getRole").invoke(talk);
                                content = (String) talk.getClass().getMethod("getContent").invoke(talk);
                            }
                            
                            if (role != null && content != null) {
                                map.put("role", role);
                                map.put("content", content);
                            }
                        } catch (Exception e) {
                            log.warn("无法处理对话对象: {}", talk, e);
                        }
                        return map;
                    })
                    .filter(map -> !map.isEmpty()) // 过滤掉空的map
                    .toList();

            redisTemplate.delete(redisKey);
            if (!conversations.isEmpty()) {
            redisTemplate.opsForList().leftPush(redisKey, conversations);
            redisTemplate.expire(redisKey, RedisConstant.AI_HISTORY_EXPIRE_TIME, TimeUnit.SECONDS);
            }

            log.info("AI对话历史保存成功（ChatMemory系统），用户ID: {}, 会话ID: {}, 对话数量: {}", 
                    userId, sessionId, aiTalkList.size());
        } catch (Exception e) {
            log.error("保存AI对话历史失败: {}", e.getMessage(), e);
            throw new RuntimeException("保存AI对话历史失败", e);
        }
    }

    /**
     * 清除AI对话历史
     * @param userId 用户ID
     */
    @Override
    public void clearAiTalks(Long userId) {
        try {
            // 清除Redis缓存
            String redisKey = RedisConstant.AI_CONTENT + userId;
            redisTemplate.delete(redisKey);
            
            log.info("AI对话历史清除成功（Redis），用户ID: {}", userId);
        } catch (Exception e) {
            log.error("清除AI对话历史失败: {}", e.getMessage(), e);
            throw new RuntimeException("清除AI对话历史失败", e);
        }
    }

    @Override
    public List<Object> listHistory(Long userId, Integer limit) {
        // 已迁移到新的会话管理系统，此方法保留用于兼容性
        log.warn("listHistory方法已废弃，请使用新的会话管理系统");
        return List.of();
    }

    /**
     * 获取AI聊天历史记录（包含问题和回答）
     * @param userId 用户ID
     * @return 聊天历史记录列表
     */
    @Override
    public List<Object> getChatHistory(Long userId) {
        // 已迁移到新的会话管理系统，此方法保留用于兼容性
        log.warn("getChatHistory方法已废弃，请使用新的会话管理系统");
            return List.of();
        }

    /**
     * 获取用户的聊天会话列表
     * @param userId 用户ID
     * @return 会话列表
     */
    public List<ChatSessionDTO> getUserSessions(Long userId) {
        return chatMemoryService.getUserSessions(userId);
    }

    /**
     * 获取指定会话的消息列表
     * @param sessionId 会话ID
     * @return 消息列表
     */
    public List<ChatMessageDTO> getSessionMessages(Long sessionId) {
        return chatMemoryService.getSessionMessages(sessionId);
    }

    /**
     * 创建新的聊天会话
     * @param userId 用户ID
     * @param initialMessage 初始消息
     * @return 会话信息
     */
    public ChatSessionDTO createChatSession(Long userId, String initialMessage) {
        return chatMemoryService.createChatSession(userId, initialMessage);
    }

    /**
     * 删除聊天会话
     * @param sessionId 会话ID
     * @param userId 用户ID
     */
    public void deleteChatSession(Long sessionId, Long userId) {
        chatMemoryService.deleteSession(sessionId, userId);
    }

    /**
     * 获取指定会话的ChatMemory对象
     * @param sessionId 会话ID
     * @return ChatMemory对象
     */
    public ChatMemory getChatMemory(Long sessionId) {
        return chatMemoryService.getChatMemory(sessionId);
    }
}


